#ifndef __SHADERPROGRAM_H__
#define __SHADERPROGRAM_H__

#include "../Common.h"
#include "Utils/Depot.h"
#include "Imaging/Image.h"
#include "Renderer.h"
#include "Shader.h"

namespace RayFrame
{
  class DLL_DECLARE ShaderProgram: public IObject
  {
  protected:
    Shader *m_vs, *m_ps;
    STRING  m_source, m_filename;
    STRING  m_log;
  public:
    ShaderProgram(){ m_vs = m_ps = NULL; };
    virtual ~ShaderProgram();

    STRING GetLog(){ return m_log; };
  
    virtual void Create(Shader* vs, Shader* fs);
    virtual void Create(STRING vsFilename, STRING fsFilename);
    virtual void Create(STRING programFilename);
    virtual void Destroy();

    virtual void Begin() = 0;
    virtual void End() = 0;
    
    virtual bool BindImage(STRING varName, Texture* image, Shader::ShaderType = Shader::VERTEX_SHADER) = 0;

    virtual Shader* CreateVertexShader() = 0;
    virtual Shader* CreatePixelShader() = 0;

    Shader* GetVertexShader(){ return m_vs; };
    Shader* GetPixelShader(){ return m_ps; };

    virtual void SetShaderParam(STRING name, const int val, Shader::ShaderType type = Shader::VERTEX_SHADER) = 0;
    virtual void SetShaderParam(STRING name, const float val, Shader::ShaderType type = Shader::VERTEX_SHADER) = 0;
    virtual void SetShaderParam(STRING name, glm::vec2 val, Shader::ShaderType type = Shader::VERTEX_SHADER) = 0;
    virtual void SetShaderParam(STRING name, glm::vec3 val, Shader::ShaderType type = Shader::VERTEX_SHADER) = 0;
    virtual void SetShaderParam(STRING name, glm::vec4 val, Shader::ShaderType type = Shader::VERTEX_SHADER) = 0;
    virtual void SetShaderParam(STRING name, glm::mat4 val, Shader::ShaderType type = Shader::VERTEX_SHADER) = 0;

    static ShaderProgram* GetDefaultShaderProgram();
    static ShaderProgram* CreateFromFile(STRING vs, STRING ps);
  };

  DECL_BUCKET_TYPE(ShaderProgramBucket, ShaderProgram);
}

#endif